import React from 'react'
import { Toast } from 'antd-mobile'
import NavHeader from 'common/NavHeader'
import http from 'utils/http'
import { getCurrentCity, setCity } from 'utils/city'
import { AutoSizer, List } from 'react-virtualized'
import 'react-virtualized/styles.css'
import styles from './index.module.scss'

const TITLE_HEIGHT = 36 // 标题的高度
const CITY_HEIGHT = 50 // 城市的高度
const HOT_CITYS = ['北京', '上海', '广州', '深圳']

class City extends React.Component {
  constructor(props) {
    super(props)
    this.listRef = React.createRef()
  }
  state = {
    cityObj: {},
    cityArr: [],
    currentIndex: 0,
  }
  async componentDidMount() {
    Toast.loading('拼命加载中...', 0)
    // 发送请求, 获取城市列表数据
    await this.getCityList()
    Toast.hide()
  }
  async getCityList() {
    const res = await http.get('/area/city?level=1')
    const { status, body } = res.data
    if (status === 200) {
      const { cityObj, cityArr } = this.parseCityList(body)

      // 处理热门城市, 应该发送ajax, 获取热门城市的数据
      const resHot = await http.get('/area/hot')
      cityArr.unshift('hot')
      cityObj['hot'] = resHot.data.body

      // 通过promise实现
      const city = await getCurrentCity()
      cityArr.unshift('#')
      cityObj['#'] = [city]

      this.setState({ cityArr, cityObj }, () => {
        // 测量全部数据行的高度
        this.listRef.current.measureAllRows()
      })
    }
  }

  // 用于处理城市列表数据
  // 思路:
  // 1. 遍历数组
  // 2. 拿到遍历的项的首字母
  // 3. 看这个首字母, 在对象中, 是否存在
  // 4. 如果不存在, 加个这个属性, 值要赋值成一个数组, 且内容就是当前项
  // 5. 如果存在, 直接将该项, 往数组中添加
  parseCityList(body) {
    // 这个城市对象: { a: [...], b: [...] }
    const cityObj = {}
    body.forEach((item) => {
      // slice(start, end) 包含start, 不包含end
      const short = item.short.slice(0, 1)
      if (short in cityObj) {
        // 存在
        cityObj[short].push(item)
      } else {
        // 不存在
        cityObj[short] = []
        cityObj[short].push(item)
      }
    })
    // 除了城市对象, 还需要一个数组 (用于决定城市展示的顺序的)
    // Object.keys(对象) 可以返回一个数组, 包含了对象中的所有的键名
    const cityArr = Object.keys(cityObj).sort()

    return {
      cityObj: cityObj,
      cityArr: cityArr,
    }
  }

  selectCity(city) {
    if (HOT_CITYS.includes(city.label)) {
      // 是热门城市的, 可以选
      // 存到本地
      setCity(city)
      // 回到上一页
      this.props.history.go(-1)
    } else {
      Toast.info('当前城市, 暂无房源信息', 3, null, false)
    }
  }

  // 该方法用于渲染一行的数据
  // key: 因为列表会对数组进行遍历, 展示内容, 需要key属性
  // index: 遍历的项的下标
  // isScrolling: 是否在滚动中, 返回一个布尔值
  // isVisible: 标记当前行, 是否可见
  // style: 就是计算出来的元素的定位的样式
  rowRenderer({ key, index, style }) {
    const { cityArr, cityObj } = this.state
    // 获取标题
    const title = cityArr[index]
    // 获取对应的城市列表
    const citys = cityObj[title]

    return (
      <div key={key} style={style} className="city-item">
        <div className="title">{this.parseTitle(title)}</div>
        {citys.map((item) => (
          <div
            key={item.value}
            className="name"
            onClick={this.selectCity.bind(this, item)}
          >
            {item.label}
          </div>
        ))}
      </div>
    )
  }
  calcRowHeight({ index }) {
    const { cityObj, cityArr } = this.state
    const title = cityArr[index]
    const citys = cityObj[title]
    return TITLE_HEIGHT + citys.length * CITY_HEIGHT
  }
  onRowsRendered({ startIndex }) {
    if (startIndex === this.state.currentIndex) return
    this.setState({
      currentIndex: startIndex,
    })
  }

  // 封装一个方法, 处理标题的展示
  parseTitle(title) {
    if (title === '#') {
      return '当前城市'
    } else if (title === 'hot') {
      return '热门城市'
    } else {
      return title.toUpperCase()
    }
  }

  handleNavClick(index) {
    // 调用list组件的 scrollToRow 方法
    this.listRef.current.scrollToRow(index)
  }

  render() {
    console.log(this.props)
    return (
      <div className={styles.city}>
        {/* 导航条 */}
        <NavHeader>城市选择</NavHeader>

        {/* 城市列表 */}
        <AutoSizer>
          {({ width, height }) => (
            <List
              ref={this.listRef}
              scrollToAlignment="start"
              width={width}
              height={height}
              rowCount={this.state.cityArr.length}
              rowHeight={this.calcRowHeight.bind(this)}
              rowRenderer={this.rowRenderer.bind(this)}
              onRowsRendered={this.onRowsRendered.bind(this)}
            />
          )}
        </AutoSizer>

        {/* 右侧索引列表 */}
        <ul className="city-index">
          {this.state.cityArr.map((item, index) => (
            <li
              className="city-index-item"
              key={item}
              onClick={this.handleNavClick.bind(this, index)}
            >
              <span
                className={
                  index === this.state.currentIndex ? 'index-active' : ''
                }
              >
                {item === 'hot' ? '热' : item.toUpperCase()}
              </span>
            </li>
          ))}
        </ul>
      </div>
    )
  }
}

export default City
